// Copyright 2013 The Go Circuit Project
// Use of this source code is governed by the license for
// The Go Circuit Project, found in the LICENSE file.
//
// Authors:
//   2013 Petar Maymounkov <p@gocircuit.org>

/*
	Package NS provides a file system interface to native Go object hierarchies.

	USR <= NS <= RH

	USR	<= NS				USR implements
	Interfaces
	_________________________________________
	SliceDir				Read() []RDIR			√
	MapDir					Read() map[string]RDIR	√
	InterfaceDir			Dir() RDIR				√
							Proc(Request,ResponseWriter)
	_________________________________________
	RDIR:											√
	InterfaceDir			interfaceFID			√
	MapDir, SliceDir		mapFID, sliceFID		√
	rh.FID					≈						√
	_________________________________________

*/
package ns

import (
	"io"
	"log"
	"reflect"

	"circuit/kit/rh"
)

// Dir stands for one of MapDir, SliceDir or InterfaceDir
type Dir interface{}

var (
	typeOfDir        = reflect.TypeOf(new(Dir)).Elem()
	typeOfFID        = reflect.TypeOf(new(rh.FID)).Elem()
	typeOfReadCloser = reflect.TypeOf(new(io.ReadCloser)).Elem()
)

// Returns one of *rhFID, *mapFID, *interfaceFID
func NewFID(name string, recv Dir) rh.FID {
	switch r := recv.(type) {
	case rh.FID:
		return newRhFID(name, r)
	case MapDir:
		return newMapFID(name, r)
	case SliceDir:
		return newSliceFID(name, r)
	case InterfaceDir:
		return newInterfaceFID(name, r)
	default:
		log.Panicf("dir what? %#T", recv)
	}
	panic("x")
}

// rhFID
type rhFID struct {
	name string
	rh.FID
}

func newRhFID(name string, fid rh.FID) *rhFID {
	return &rhFID{
		name: name,
		FID:  fid,
	}
}

func (rf *rhFID) Stat() (dir *rh.Dir, err error) {
	dir, err = rf.FID.Stat()
	if err != nil {
		return nil, err
	}
	dir.Name = rf.name
	return dir, nil
}
